<template>
  <div class="bpmn-container">
    <div class="explain">
      点击左下角下载 XML，将文件上传到
      <a-button type="link" href="https://demo.bpmn.io/" target="_blank">
        BPMN Demo
      </a-button>
      即可使用
    </div>
    <div id="graph" ref="container"></div>
    <div class="graph-io">
      <span title="下载 XML" @mousedown="downloadXml">
        <img
          src="https://cdn.jsdelivr.net/gh/Logic-Flow/static@latest/docs/examples/case/bussiness/bpmn/download.png"
          alt="下载XML"
        />
      </span>
      <span id="upload-xml" title="上传 XML">
        <input
          type="file"
          class="upload"
          @change="uploadXml"
        />
        <img
          class="upload-img"
          src="https://cdn.jsdelivr.net/gh/Logic-Flow/static@latest/docs/examples/case/bussiness/bpmn/upload.png"
          alt="上传XML"
        />
      </span>
    </div>
  </div>
</template>

<script lang="ts">
import { defineComponent } from 'vue'

export default defineComponent({
  name: 'BpmnFlow'
})
</script>

<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { Button as AButton } from 'ant-design-vue'
import LogicFlow from '@logicflow/core'
import { BpmnElement, BpmnXmlAdapter, Control, Menu, SelectionSelect, DndPanel } from '@logicflow/extension'
import '@logicflow/core/es/index.css'
import '@logicflow/extension/es/index.css'

const container = ref<HTMLElement | null>(null)
const lfRef = ref<LogicFlow | null>(null)

const download = (filename: string, text: string) => {
  const element = document.createElement('a')
  element.setAttribute(
    'href',
    'data:text/plain;charset=utf-8,' + encodeURIComponent(text)
  )
  element.setAttribute('download', filename)
  element.style.display = 'none'
  document.body.appendChild(element)
  element.click()
  document.body.removeChild(element)
}

const downloadXml = () => {
  if (lfRef.value) {
    const data = lfRef.value.getGraphData() as string
    download('logic-flow.xml', data)
  }
}

const uploadXml = (ev: Event) => {
  const target = ev.target as HTMLInputElement
  const file = target.files?.[0]
  if (!file) return

  const reader = new FileReader()
  reader.onload = (event: ProgressEvent<FileReader>) => {
    if (event.target && lfRef.value) {
      const xml = event.target.result as string
      lfRef.value.render(xml)
    }
  }
  reader.readAsText(file)
}

onMounted(() => {
  if (container.value) {
    lfRef.value = new LogicFlow({
      container: container.value,
      stopZoomGraph: true,
      metaKeyMultipleSelected: true,
      grid: true,
      keyboard: {
        enabled: true,
      },
      snapline: true,
      plugins: [
        BpmnElement,
        BpmnXmlAdapter,
        Control,
        Menu,
        SelectionSelect,
        DndPanel,
      ],
    })

    lfRef.value.setPatternItems([
      {
        label: '选区',
        icon: '',
        callback: () => {
          lfRef.value?.openSelectionSelect()
          lfRef.value?.once('selection:selected', () => {
            lfRef.value?.closeSelectionSelect()
          })
        },
      },
      {
        type: 'bpmn:startEvent',
        label: '开始',
        text: '开始',
        icon: '',
      },
      {
        type: 'bpmn:userTask',
        label: '用户任务',
        text: '用户任务',
        icon: '',
      },
      {
        type: 'bpmn:serviceTask',
        label: '系统任务',
        text: '系统任务',
        icon: '',
      },
      {
        type: 'bpmn:exclusiveGateway',
        label: '条件判断',
        text: '条件判断',
        icon: '',
      },
      {
        type: 'bpmn:endEvent',
        label: '结束',
        text: '结束',
        icon: '',
      },
    ])

    lfRef.value.render({})
  }
})

defineExpose({
  container,
  lfRef,
  downloadXml,
  uploadXml
})
</script>

<style>
.bpmn-container {
  width: 100%;
  height: 100%;
  position: relative;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.explain {
  height: 30px;
  line-height: 30px;
  padding: 0 10px;
  background: #f5f5f5;
  border-bottom: 1px solid #e8e8e8;
  flex-shrink: 0;
  color: #333;
}

#graph {
  flex: 1;
  width: 100%;
  min-height: 0;
  background: #fff;
  overflow: hidden;
  position: relative;
}

.graph-io {
  position: absolute;
  left: 10px;
  bottom: 10px;
  z-index: 9999;
  background: rgba(255,255,255,0.8);
  box-shadow: 0 1px 4px rgba(0,0,0,.3);
  padding: 10px;
  display: flex;
  border-radius: 4px;
}

.graph-io > span {
  margin: 0 5px;
  cursor: pointer;
}

#upload-xml {
  position: relative;
  overflow: hidden;
  display: inline-block;
  cursor: pointer;
}

.upload {
  position: absolute;
  z-index: 99;
  left: 0;
  top: 0;
  opacity: 0;
  cursor: pointer;
}

.upload::-webkit-file-upload-button {
  cursor: pointer;
}

.upload-img {
  width: 26px;
}
</style> 